package com.dhz.common.web.controller;

import com.alibaba.fastjson.JSON;
import com.dhz.common.base.Code;
import com.dhz.common.base.ServiceResult;
import com.dhz.common.base.SysCode;
import com.dhz.common.exception.GenericException;
import com.dhz.common.web.utils.Servlets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 远程调用Controller基类，只要用户处理业务异常
 */
public class BaseRestController {
    /** DEFAULT 日志 */
    protected Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * <p>系统异常收集处理方法，与{@link com.dhz.common.web.exception.ExceptionHandler#doResolveException(HttpServletRequest, HttpServletResponse, Object, Exception)} 一起完成大部分的异常处理；
     * 如果这两个地方都不能正确处理，则异常将会交由web.xml中的配置处理</p>
     *
     * <p>拦截器中抛出的异常这里捕获不到，{@link com.dhz.common.web.exception.ExceptionHandler#doResolveException(HttpServletRequest, HttpServletResponse, Object, Exception)}处理</p>
     *
     * @param request {@link HttpServletRequest} 请求的request对象
     * @param e {@link Exception} 异常实例
     * @return 根据异常类型，返回对应的ServiceCode - {@link Code}
     */
    @ExceptionHandler
    public Object handlerException(HttpServletRequest request, Exception e) {

        // 异步记录日志
        // SpringUtils.getBean(AsyncLogQueue.class).post(new AsyncLogEvent.EventDataSysErr(request.getRequestURI(), Servlets.getRequestParams(request), e));
        logger.error("请求接口 ==> {}\n请求参数 ==> {}", request.getRequestURI(), JSON.toJSONString(Servlets.getRequestParams(request)), e);

        // 异常类型判断，返回不同的错误代码
        // 1.业务自定义的异常
        if (e instanceof GenericException) {
            return new ServiceResult(((GenericException) e).getCode(), e.getMessage());
        }
        // 2.Spring MVC 参数绑定失败异常
        else if (e instanceof BindException) {
            return new ServiceResult(SysCode.ERR_PARAM);
        }
        // 3.Spring MVC 参数不匹配异常
        else if (e instanceof TypeMismatchException) {
            return new ServiceResult(SysCode.ERR_PARAM, "参数不匹配");
        }
        else if (e instanceof MissingServletRequestParameterException) {
            return new ServiceResult(SysCode.ERR_PARAM, "参数不存在或类型错误");
        }
        // n.未知异常
        else {
            return new ServiceResult(SysCode.ERR_SERVER);
        }

    }


}
